home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / graphic / vgamaze4.zip / PLOT3D.CPP < prev    next >
C/C++ Source or Header  |  1994-03-02  |  39KB  |  938 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <math.h>
  4. #include <stdlib.h>
  5. #include <iostream.h>
  6. #include "titillat.h"
  7. #include "plot3d.h"
  8.  
  9. #ifndef TRUE
  10. #define TRUE -1
  11. #endif
  12. #ifndef FALSE
  13. #define FALSE 0
  14. #endif
  15.  
  16. typedef struct
  17.           {
  18.             int x;
  19.             int y;
  20.           } box_rec;
  21.  
  22. plot3d::plot3d()
  23.   {
  24.     prime_array_allocated=FALSE;
  25.     plot_prepared=FALSE;
  26.   }
  27.  
  28. plot3d::~plot3d()
  29.   {
  30.     if (prime_array_allocated)
  31.       delete prime_array;
  32.   }
  33.  
  34. int plot3d::prepare_plot(
  35.   double (*f)(double,double),
  36.   double x_min,
  37.   double x_max,
  38.   double y_min,
  39.   double y_max,
  40.   int    (*external_to_plot)(double,double),
  41.   int    (*red)(double,double),
  42.   int    x_division_count,
  43.   int    y_division_count,
  44.   double rotation_in_degrees,
  45.   double tilt_in_degrees,
  46.   double light_x,
  47.   double light_y,
  48.   double light_z)
  49. //      This function prepares a plot for generation.  If returns TRUE if
  50. // and only if it is successful.  If it is successful, "plot" may be called
  51. // to actually generate the plot.  Its parameters are as follow:
  52. //
  53. //           f -- z=f(x,y), the function to be plotted.  Before the plot is
  54. //      tilted or rotated, the z-axis runs from the bottom to the top of the
  55. //      display, the y-axis runs from the left to the right of the display,
  56. //      and the x-axis runs out of the display.
  57. //
  58. //           x_min -- the minimum value of x to be plotted.
  59. //
  60. //           x_max -- the maximum value of x to be plotted.
  61. //
  62. //           y_min -- the minimum value of y to be plotted.
  63. //
  64. //           y_max -- the maximum value of y to be plotted.
  65. //
  66. //           external_to_plot -- a function that returns TRUE if and only if a
  67. //      point should be omitted from the plot.
  68. //
  69. //           red -- a function that returns TRUE if and only if a point should
  70. //      be flagged for highlighting.  A point should be so flagged only if it
  71. //      can be seen in the final plot.
  72. //
  73. //           x_division_count -- the number of x divisions to be used in
  74. //      constructing the plot.  At least two must be specified.
  75. //
  76. //           y_division_count -- the number of y divisions to be used in
  77. //      constructing the plot.  At least two must be specified.
  78. //
  79. //           rotation_in_degrees -- rotation (degrees) about an axis parallel to
  80. //      the z-axis and through the center of the surface.
  81. //
  82. //           tilt_in_degrees -- tilt (degrees) about an axis through the center
  83. //      of the surface and parallel to a line from the lower left hand corner of
  84. //      the display to the lower right hand corner of the display.  The plot is
  85. //      tilted after it is rotated.
  86. //
  87. //           (light_x,light_y,light_z) -- a vector pointing to the light source
  88. //      (at infinity).  The light source remains fixed while the plot is rotated
  89. //      or tilted.
  90.     {
  91.       int       display_ready;
  92.       prime_rec initialized_prime_rec;
  93.       int       result;
  94.       int       x_byte_num;
  95.  
  96.       plot_prepared=FALSE;
  97.       if (prime_array_allocated)
  98.         {
  99.           delete prime_array;
  100.           prime_array_allocated=FALSE;
  101.         }
  102.       num_x_divisions=x_division_count;
  103.       num_y_divisions=y_division_count;
  104.       num_primes=(long) num_x_divisions;
  105.       num_primes*=((long) num_y_divisions);
  106.         // Number of quadrilaterals composing the plot.
  107.       initialized_prime_rec.base_z=(unsigned char) '\0';
  108.       initialized_prime_rec.color=(unsigned char) '\0';
  109.       initialized_prime_rec.x=(float) 0.0;
  110.       initialized_prime_rec.y=(float) 0.0;
  111.       initialized_prime_rec.z=(float) 0.0;
  112.       initialized_prime_rec.x_division_index=0;
  113.       initialized_prime_rec.y_division_index=0;
  114.       prime_array=new varray<prime_rec>(initialized_prime_rec,num_primes,5);
  115.         // Virtual array of quadrilaterals composing the plot.
  116.       if (prime_array_allocated=(prime_array->allocated()))
  117.         {
  118.           titillator_ptr=new titillator;
  119.           rotation=rotation_in_degrees;
  120.           tilt=tilt_in_degrees;
  121.           light.x=light_x;
  122.           light.y=light_y;
  123.           light.z=light_z;
  124.           evaluate_and_transform(f,x_min,x_max,y_min,y_max,
  125.            num_x_divisions,num_y_divisions,rotation,tilt,
  126.            external_to_plot,red);
  127.             // Compute the vertices, etc. of the quadrilaterals composing the
  128.             // plot.
  129.           shade();
  130.             // Compute the shade of gray for each quadrilateral composing the
  131.             // plot.
  132.           adjust_perspective();
  133.             // Force parallel lines running away from the viewer to converge at
  134.             // the horizon.
  135.           sort_back_to_front();
  136.           plot_prepared=TRUE;
  137.           delete titillator_ptr;
  138.           display_ready=display_initialized();
  139.             // Do whatever is necessary to prepare the display.
  140.         }
  141.       return (prime_array_allocated & display_ready);
  142.     }
  143.  
  144. void plot3d::evaluate_and_transform(
  145.   double (*f)(double,double),
  146.   double x_min,
  147.   double x_max,
  148.   double y_min,
  149.   double y_max,
  150.   int    num_x_divisions,
  151.   int    num_y_divisions,
  152.   double rotation,
  153.   double tilt,
  154.   int    (*external_to_plot)(double,double),
  155.   int    (*red)(double,double))
  156. // Compute the vertices, etc. for each quadrilateral composing the plot.
  157.     {
  158.       double    cos_rotation;
  159.       double    cos_tilt;
  160.       double    degrees_per_radian;
  161.       double    magnitude;
  162.       prime_rec *prime;
  163.       long      prime_num;
  164.       double    radians;
  165.       double    sin_rotation;
  166.       double    sin_tilt;
  167.       double    tem_x;
  168.       double    tem_y;
  169.       double    tem_z;
  170.       double    x;
  171.       double    x_delta;
  172.       int       x_division_num;
  173.       double    x_rotated;
  174.       double    y;
  175.       double    y_delta;
  176.       int       y_division_num;
  177.       double    z;
  178.  
  179.       degrees_per_radian=45.0/atan(1.0);
  180.       radians=tilt/degrees_per_radian;
  181.       cos_tilt=cos(radians);
  182.       sin_tilt=sin(radians);
  183.       radians=rotation/degrees_per_radian;
  184.       cos_rotation=cos(radians);
  185.       sin_rotation=sin(radians);
  186.       z=f(x_min,y_min);
  187.       x_rotated=x_min*cos_rotation+y_min*sin_rotation;
  188.       y_prime_min=-x_min*sin_rotation+y_min*cos_rotation;
  189.       z_prime_min=-x_rotated*sin_tilt+z*cos_tilt;
  190.       y_prime_max=y_prime_min;
  191.       z_prime_max=z_prime_min;
  192.       x_prime_max=x_rotated*cos_tilt+z*sin_tilt;
  193.       x_delta=(double) (num_x_divisions-1);
  194.       x_delta=(x_max-x_min)/x_delta;
  195.       y_delta=(double) (num_y_divisions-1);
  196.       y_delta=(y_max-y_min)/y_delta;
  197.       x=x_min;
  198.       prime_num=(long) 0;
  199.       for (x_division_num=0; x_division_num < num_x_divisions; x_division_num++)
  200.         {
  201.           titillator_ptr->titillate();
  202.           y=y_min;
  203.           for (y_division_num=0; y_division_num < num_y_divisions;
  204.            y_division_num++)
  205.             {
  206.               z=f(x,y);
  207.               prime=prime_array->vm_ptr(prime_num);
  208.               if (external_to_plot(x,y))
  209.                 prime->base_z=(unsigned char) 3;
  210.               else
  211.                 if (red(x,y))
  212.                   prime->base_z=(unsigned char) 2;
  213.                 else
  214.                   prime->base_z=(unsigned char) 1;
  215.               prime->x_division_index=x_division_num;
  216.               prime->y_division_index=y_division_num;
  217.               x_rotated=x*cos_rotation+y*sin_rotation;
  218.               tem_y=(-x*sin_rotation+y*cos_rotation);
  219.               prime->y=(float) tem_y;
  220.               tem_x=(x_rotated*cos_tilt+z*sin_tilt);
  221.               prime->x=(float) tem_x;
  222.               tem_z=(-x_rotated*sin_tilt+z*cos_tilt);
  223.               prime->z=(float) tem_z;
  224.               if (tem_x > x_prime_max)
  225.                 x_prime_max=tem_x;
  226.               if (tem_y < y_prime_min)
  227.                 y_prime_min=tem_y;
  228.               if (tem_y > y_prime_max)
  229.                 y_prime_max=tem_y;
  230.               if (tem_z < z_prime_min)
  231.                 z_prime_min=tem_z;
  232.               if (tem_z > z_prime_max)
  233.                 z_prime_max=tem_z;
  234.               y+=y_delta;
  235.               prime_num++;
  236.             }
  237.           x+=x_delta;
  238.